package comm;

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.FileOutputStream;

import javax.imageio.ImageIO;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class ThumbnailUtil {
	private static BufferedImage getScaledInstance(BufferedImage img,
			int targetWidth,
			int targetHeight,
			boolean higherQuality) {
		int type = (img.getTransparency() == Transparency.OPAQUE) ?
				BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
		BufferedImage ret = img;
		int w, h;
		if (higherQuality) {
			w = img.getWidth();
			h = img.getHeight();
		} else {
			w = targetWidth;
			h = targetHeight;
		}

		do {
			if (higherQuality && w > targetWidth) {
				w /= 2;
				if (w < targetWidth) {
					w = targetWidth;
				}
			}
			if (higherQuality && h > targetHeight) {
				h /= 2;
				if (h < targetHeight) {
					h = targetHeight;
				}
			}
			BufferedImage tmp = new BufferedImage(w, h, type);
			Graphics2D g2 = tmp.createGraphics();
			g2.setComposite(AlphaComposite.Src);
			g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
			g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			g2.drawImage(ret, 0, 0, w, h, null);
			g2.dispose();

			ret = tmp;
		} while (w != targetWidth || h != targetHeight);
		return ret;
	}
	private static void createThumbnail(String originalFilename, BufferedImage img, int length, int length2) throws Exception {
		int thumbW = 0;
		int thumbH = 0;
		if (img.getWidth() < length) {
			thumbW = img.getWidth();
			//thumbH = img.getHeight();
		} else {
			/*double scale = (double)length/(double)img.getHeight();
			if (img.getWidth() > img.getHeight()) {
				scale = (double)length/(double)img.getWidth();
			}*/
			
			double scale = (double)length/(double)img.getWidth();
			thumbW = (int)(img.getWidth()*scale);
			//thumbH = (int)(img.getHeight()*scale);
		}
		if (img.getHeight() < length2) {
			//thumbW = img.getHeight();
			thumbH = img.getHeight();
		} else {
			/*double scale = (double)length/(double)img.getHeight();
			if (img.getWidth() > img.getHeight()) {
				scale = (double)length/(double)img.getWidth();
			}*/
			
			double scale = (double)length2/(double)img.getHeight();
			//thumbW = (int)(img.getWidth()*scale);
			thumbH = (int)(img.getHeight()*scale);
		}

		BufferedImage ret = getScaledInstance(img, thumbW, thumbH, true);
		if (img.getWidth() > length) {
			ret = filterSharpen(ret);
		}
		
		String thumbnailFilename = createThumbnailFilename(originalFilename, length);
		
		FileOutputStream out = new FileOutputStream(new File(thumbnailFilename));
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(ret);
		param.setQuality(1f, true);
		encoder.setJPEGEncodeParam(param);
		encoder.encode(ret);
	}
	
	private static BufferedImage filterSharpen(BufferedImage image) {
		float data[] = {   0.0f, -0.5f, 0.0f,
				-0.5f, 3.0f, -0.5f,
				0.0f, -0.5f, 0.0f
		};
		Kernel kernel = new Kernel(3, 3, data);
		ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
		return convolve.filter(image, null);

	}

	private static void createThumbnail(String originalFilename, BufferedImage img, int length) throws Exception {
		int thumbW = 0;
		int thumbH = 0;
		if (img.getWidth() < length) {
			thumbW = img.getWidth();
			thumbH = img.getHeight();
		} else {
			/*double scale = (double)length/(double)img.getHeight();
			if (img.getWidth() > img.getHeight()) {
				scale = (double)length/(double)img.getWidth();
			}*/
			
			double scale = (double)length/(double)img.getWidth();
			thumbW = (int)(img.getWidth()*scale);
			thumbH = (int)(img.getHeight()*scale);
		}
		

		BufferedImage ret = getScaledInstance(img, thumbW, thumbH, true);
		if (img.getWidth() > length) {
			ret = filterSharpen(ret);
		}
		
		String thumbnailFilename = createThumbnailFilename(originalFilename, length);
		
		FileOutputStream out = new FileOutputStream(new File(thumbnailFilename));
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(ret);
		param.setQuality(1f, true);
		encoder.setJPEGEncodeParam(param);
		encoder.encode(ret);
	}

	/**
	 * �뜽�꽕�씪 �씠誘몄�� �깮�꽦
	 * 
	 * @param originalFilename
	 * @param thumbnailFilename
	 * @param length
	 * @throws Exception
	 */
	public static void createThumbnail(String originalFilename, int length) throws Exception { 
		BufferedImage img = ImageIO.read(new File(originalFilename));
		createThumbnail(originalFilename, img, length);
	}
	/**
	 * 媛�濡� �꽭濡� �궗�씠利� 議곗젅 �뜽�꽕�씪 �씠誘몄�� �깮�꽦
	 * @param originalFilename
	 * @param length
	 * @param width
	 * @throws Exception
	 */
	public static void createThumbnail(String originalFilename, int length , int width) throws Exception { 
		BufferedImage img = ImageIO.read(new File(originalFilename));
		createThumbnail(originalFilename, img, length , width);
	}

	/**
	 * �젙�궗媛곹삎 �뜽�꽕�씪 �씠誘몄�� �깮�꽦
	 * 
	 * @param originalFilename
	 * @param thumbnailFilename
	 * @param length
	 * @throws Exception
	 */
	public static void createSquareThumbnail(String originalFilename, int length) throws Exception {
		BufferedImage img = ImageIO.read(new File(originalFilename));
		int minLength = img.getWidth() > img.getHeight() ? img.getHeight() : img.getWidth();

		BufferedImage tmp = null;
		if (img.getWidth() > img.getHeight()) {
			int s = (int)((img.getWidth() - img.getHeight()) / 2.0);
			tmp = img.getSubimage(s, 0, minLength, minLength);
		} else {
			int s = (int)((img.getHeight() - img.getWidth()) / 2.0);
			tmp = img.getSubimage(0, s, minLength, minLength);
		}

		createThumbnail(originalFilename, tmp, length);
	}
	
	public static String createThumbnailFilename(String filename, int length) {
		String thumbnailFilename;
		int dot = filename.lastIndexOf('.');
		if (dot == -1) { //�솗�옣�옄媛� �뾾�쑝硫�
			thumbnailFilename = filename + "_thumb" + length;
		} else {
			String name = filename.substring(0, dot);
			String ext = filename.substring(dot);
			thumbnailFilename = name + "_thumb" + length + ext;
		}
		return thumbnailFilename;
	}
	
	public static void main(String[] args) throws Exception {
		createThumbnail("d:\\height.jpg", 300);
		createSquareThumbnail("d:\\height.jpg", 75);
	}
}
